#include<reg52.h>
typedef unsigned char uchar;
typedef unsigned int uint;

/*宏定义区*/
#define TH01 1000//定时器溢出
#define TL01 1000
#define white 0
#define black 1
#define forward_speed 35 //前进速度
#define adju_speed  25//调整速度
#define turn_speed 30 //转弯速度
#define low_speed 15//慢速

/*引脚定义区*/
sbit f_LEA = P1^0; //前左使能端
sbit f_REA = P1^1; //前右使能端
sbit b_LEA = P1^2; //后左使能端
sbit b_REA = P1^3; //后右使能端
/*前轮*/
sbit f_LIN1 = P2^0;
sbit f_LIN2 = P2^1;
sbit f_RIN1 = P2^2;
sbit f_RIN2 = P2^3;
/*后轮*/
sbit b_LIN1 = P2^4;
sbit b_LIN2 = P2^5;
sbit b_RIN1 = P2^6;
sbit b_RIN2 = P2^7;
/*传感器*/
sbit red1 = P1^4;
sbit red2 = P1^5;
sbit red3 = P1^6;
sbit red4 = P1^7;

/*全局变量定义区*/
uchar cout;//定时器1自动填充
uint flag;

void delay(uint ms)//延时
{
	uint i;
	for (ms;ms > 0;ms--)
	for (i = 110;i > 0;i--);
}

void high_EA()//四轮全部使能端拉高
{
	f_LEA = 1;
	f_REA = 1;
	b_LEA = 1;
	b_REA = 1;
}

void low_EA()//四轮全部使能端拉低
{	
	f_LEA = 0;
	f_REA = 0;
	b_LEA = 0;
	b_REA = 0;
}

/*pwm差速调节*/
void front_left_pwm(bit flag,uint speed)//前左电机正反转，占空比=speed/cout,flag=1为正转，flag=0为反转
{
	if(flag == 1)
	{
		f_LIN1 = 0;
		if(cout <= speed) 	
			f_LIN2 = 1;
		else f_LIN2 = 0;
	}
	else//flag==0
	{
		f_LIN2 = 0;
		if(cout <= speed)
			f_LIN1 = 1;
		else f_LIN1 = 0;
	}
}

void front_right_pwm(bit flag,uint speed)//前右电机正反转，占空比=speed/cout,flag=1为正转，flag=0为反转
{
		if(flag == 1)
	{
		f_RIN1 = 0;
		if(cout <= speed) 	
			f_RIN2 = 1;
		else f_RIN2 = 0;
	}
	else//flag==0
	{
		f_RIN2 = 0;
		if(cout <= speed)
			f_RIN1 = 1;
		else f_RIN1 = 0;
	}
}

void back_left_pwm(bit flag,uint speed)//后左电机正反转，占空比=speed/cout,flag=1为正转，flag=0为反转
{
		if(flag == 1)
	{
		b_LIN1 = 1;
		if(cout <= speed) 	
			b_LIN2 = 0;
		else b_LIN2 = 1;
	}
	else//flag==0
	{
		b_LIN2 = 1;
		if(cout <= speed)
			b_LIN1 = 0;
		else b_LIN1 = 1;
	}
}

void back_right_pwm(bit flag,uint speed)//后右电机正反转，占空比==speed/cout,flag=1为正转，flag=0为反转
{
			if(flag == 1)
	{
		b_RIN1 = 0;
		if(cout <= speed) 	
			b_RIN2 = 1;
		else b_RIN2 = 0;
	}
	else//flag==0
	{
		b_RIN2 = 0;
		if(cout <= speed)
			b_RIN1 = 1;
		else b_RIN1 = 0;
	}
}

/*小车转向控制及差速控制*/
/*正转为1,反转为0  速度0~9*/
void forward()//全速前进
{
	front_left_pwm(1,forward_speed);
	front_right_pwm(1,forward_speed);
	back_left_pwm(1,forward_speed);
	back_right_pwm(1,forward_speed);
}

void back()//刹车
{
	front_left_pwm(0,forward_speed);
	front_right_pwm(0,forward_speed);
	back_left_pwm(1,forward_speed);
	back_right_pwm(1,forward_speed);
}
	

void low_forward()//低速前进
{
		front_left_pwm(1,low_speed);
		front_right_pwm(1,low_speed);
		back_left_pwm(1,low_speed);
		back_right_pwm(1,low_speed);
}

void turn_left()//原地左转 左边两轮反转，右边两轮正转
{
	front_left_pwm(0,turn_speed);
	front_right_pwm(1,turn_speed);
	back_left_pwm(0,turn_speed);
	back_right_pwm(1,turn_speed);
}

void turn_right()//原地右转 右边两轮反转，左边两轮正转
{
	front_left_pwm(1,turn_speed);
	front_right_pwm(0,turn_speed);
	back_left_pwm(1,turn_speed);
	back_right_pwm(0,turn_speed);
}

void adju_left()//左调整
{
		front_left_pwm(0,adju_speed);
		front_right_pwm	(1,adju_speed);
		back_left_pwm(0,adju_speed);
		back_right_pwm(1,adju_speed);
}
void adju_right()//右调整
{
		front_left_pwm(1,adju_speed);
		front_right_pwm(0,adju_speed);
		back_left_pwm(1,adju_speed);
		back_right_pwm(0,adju_speed);
}

void seek()//循迹执行
{
	uint ms=350;
	uint ms1;
	if(red1 == white && red2 == black && red3 == black && red4 == white)//直行
		flag = 1;
	else if(red2 == white && red3 == black)//左偏了
		flag = 2;
	else if(red2 == black && red3 == white)//右偏了
		flag = 3;
	else if(red1 == black && red2 == black && red3 == black && red4 == white)//左转检测
		flag = 4;
	else if(red1 == white && red2 == black && red3 == black && red4 == black)//右转检测
		flag = 5;
	else if(red1 == black && red2 == black && red3 == black && red4 == black)//检测T型路口
		flag = 6;
	switch(flag)
	{
		case 1:
		{
			forward();
			break;
		}
		case 2:
		{
			while(red2 == white || red3 == white)//左调整
				adju_right();
			break;
		}
		case 3:
		{
			while(red2 == white || red3 == white)//右调整
				adju_left();
			break;
		}
		/*暴力右转*/
		case 4://左边检测到  ，前方有则直行，否则右转
		{
			for(ms1=ms;ms1>0;ms1--)
			low_forward();
			back();
			delay(20);
			if(red2 == black && red3 == black)
			{
				break;
			}
			else if(red2 == white && red3 == white)
			{
				while(red1 == white)
					turn_left();
				while(red2 == white)
					turn_left();
				turn_right();
				delay(20);
				break;
			}
		}
		case 5://右边检测到  直接右转
		{
			for(ms1=ms;ms1>0;ms1--)
			low_forward();
			back();
			delay(20);
			while(red4 == white)
				turn_right();
			while(red3 == white)
				turn_right();
			turn_left();
			delay(20);
			break;
		}
		case 6://检测到T字型路口  默认右转
		{
			for(ms1=ms;ms1>0;ms1--)
			low_forward();
			back();
			delay(20);
			while(red4 == white)
				turn_right();
			while(red3 == white)
				turn_right();
			turn_left();
			delay(20);
			break;
		}
		/*暴力左转*/
//			case 4://左边检测到 直接左转
//		{
//			for(ms1=ms;ms1>0;ms1--)
//			low_forward();
//			back();
//			delay(20);
//			while(red1 == white)
//				turn_left();
//			turn_right();
//			while(red2 == white)
//				turn_left();
//			turn_right();
//			delay(20);
//			break;
//			}
//		}
//		case 5://右边检测到  若中间检测到则直行，否则直接右转
//		{
//			for(ms1=ms;ms1>0;ms1--)
//			low_forward();
//			back();
//			delay(20);
//			if(red2 == black && red3 == black)
//			{
//				break;
//			}
//			else if(red2 == white && red3 == white)
//			{
//			while(red4 == white)
//				turn_right();
//			turn_left();
//			while(red3 == white)
//				turn_right();
//			turn_left();
//			delay(20);
//			break;
//			}
//		}
//		case 6://检测到T字型路口  默认左转
//		{
//			for(ms1=ms;ms1>0;ms1--)
//			low_forward();
//			back();
//			delay(20);
//			while(red1 == white)
//			turn_left();
//			turn_right();		
//			while(red2 == white)
//			turn_left();
//			turn_right();
//			delay(20);
//			break;
//		}
	}
}

void init_time()//定时器初始化	
{
	TMOD = 0X10;
	TH0 = (65535 - TH01) / 256;
	TL0 = (65535 - TL01) % 256;
	EA = 1;
	TR0 = 1;
	ET0 = 1;
}

void main()
{
	cout = 0;
	init_time();//定时器初始化
	low_EA();
	while(red2 == white && red3 == white);
	high_EA();
	while(1)
	{
		seek();
	}
}

void InterruptTime1() interrupt 1
{
	TH0 = (65535 - TH01) / 256;
	TL0 = (65535 - TH01) % 256;
	cout++;
	if(cout>100)
		cout=0;
}